/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.mvc.plugin;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import com.zhg2yqq.wheels.mvc.annotation.XssEscape;
import com.zhg2yqq.wheels.mvc.annotation.XssField;

/**
 *
 * @version zhg2yqq v1.0
 * @author zhg2yqq, 2022年12月4日
 */

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.HtmlUtil;

public class XssEscapeRequestBodyArgumentResolver extends RequestResponseBodyMethodProcessor {
    public XssEscapeRequestBodyArgumentResolver(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public XssEscapeRequestBodyArgumentResolver(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager) {
        super(converters, manager);
    }

    public XssEscapeRequestBodyArgumentResolver(List<HttpMessageConverter<?>> converters, List<Object> requestResponseBodyAdvice) {
        super(converters, requestResponseBodyAdvice);
    }

    public XssEscapeRequestBodyArgumentResolver(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager, List<Object> requestResponseBodyAdvice) {
        super(converters, manager, requestResponseBodyAdvice);
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        boolean s = super.supportsParameter(parameter) && parameter.hasParameterAnnotation(XssEscape.class);
        return s;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Object o = super.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
        if (o == null) {
            return o;
        }
        Field[] fields = ReflectUtil.getFields(o.getClass(),
                f -> f.isAnnotationPresent(XssField.class) && String.class.equals(f.getType()));
        Arrays.stream(fields).forEach(f -> {
            String v = (String) ReflectUtil.getFieldValue(o, f);
            if (v != null) {
                ReflectUtil.setFieldValue(o, f, HtmlUtil.escape(v));
            }
        });
        return o;
    }
}
